 /**
 * TDS PEC 4
 * Grupo 3H2M
 *
 * El paquete <code>edu.uoc.tds.pec4.server.bbdd</code> agrupa todas las clases
 * que encapsulan los objetos de acceso a datos (DAO),para realizar el acceso
 * a datos. La base de datos es PostgreSQL.
 */
package edu.uoc.tds.pec4.server.bbdd;

import edu.uoc.tds.pec4.beans.CiudadDTO;
import edu.uoc.tds.pec4.beans.RankingAulaDTO;
import edu.uoc.tds.pec4.beans.RankingClienteDTO;
import edu.uoc.tds.pec4.beans.RankingLocalizacionDTO;
import edu.uoc.tds.pec4.common.filters.FiltroFechas;
import edu.uoc.tds.pec4.common.filters.FiltroLocalizacion;
import edu.uoc.tds.pec4.common.util.Constantes;
import edu.uoc.tds.pec4.server.bbdd.exceptions.DataBaseDAOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * La clase <code>IncidenciaDAO</code> es el componente de software que suministra
 * una interfaz común entre la aplicación y la base de datos, relacionada con la
 * gestión de las incidencias y sus anotaciones.<br />
 * Extiende la clase <code>DataBaseDAO</code><br />
 * 
 * @author	Isabel Guerra Monclova
 * @version	05/12/2011
 * @see         edu.uoc.tds.pec4.server.bbdd.exceptions.DataBaseDAOException
 */
public class RankingDAO extends DataBaseDAO implements IRankingDAO {
    
    private static final int MILLISECONDS_IN_DAY = 1000 * 60 * 60 * 24;
    
    public RankingDAO () throws DataBaseDAOException {
        super();
    }
    
    @Override
    public List<RankingAulaDTO> getRankingAulas(FiltroLocalizacion filtroLoc, FiltroFechas filtroFechas, Boolean agrupaMeses, Boolean agrupaLocal, int top) throws DataBaseDAOException {
        
        List<RankingAulaDTO> ranking = null;
        
        try {
            //Ranking agrupado por días de un período
            if(!agrupaMeses) {           
                ranking = obtenerRankingAulas (filtroLoc,filtroFechas,top);
            } else {
                //Ranking agrupado por meses
                //Para no considerar saltos entre años, para agrupar por meses el año
                //debe ser el mismo, siendo la fechaInicio inferior a fechaFin
                ranking = obtenerRankingAulaMeses (filtroLoc,filtroFechas,top);
                              
            }
            
        } catch (SQLException eS) {
            throw new DataBaseDAOException(DataBaseDAOException.CAN_NOT_EXECUTEQUERY
                    + Constantes.SL + eS.getMessage());
        }

        return ranking;
    }

    @Override
    public List<RankingLocalizacionDTO> getRankingLocalizaciones(FiltroLocalizacion filtroLoc, FiltroFechas filtroFechas, Boolean agrupaMeses, Boolean agrupaLocal, int top) throws DataBaseDAOException {

        List<RankingLocalizacionDTO> ranking = null;
        
        try {
            //Ranking agrupado por días de un período
            if(!agrupaMeses) {
                ranking = obtenerRankingLocalizacion(filtroLoc, filtroFechas, top);
            } else {
                //Ranking agrupado por meses
                ranking = obtenerRankingLocalizacionMeses (filtroLoc,filtroFechas, top);
            }
            
        } catch (SQLException eS) {
            throw new DataBaseDAOException(DataBaseDAOException.CAN_NOT_EXECUTEQUERY
                    + Constantes.SL + eS.getMessage());
        }

        return ranking;
        
    }

    @Override
    public List<RankingClienteDTO> getRankingClientes(FiltroLocalizacion filtroLoc, FiltroFechas filtroFechas, Boolean agrupaMeses, Boolean agrupaLocal, int top) throws DataBaseDAOException {

        List<RankingClienteDTO> ranking = null;
        try {
            //Ranking agrupado por días de un período
            if(!agrupaMeses) {
                ranking = obtenerRankingCliente(filtroLoc, filtroFechas, top);
            } else {
                //Ranking agrupado por meses
                ranking = obtenerRankingClienteMeses (filtroLoc,filtroFechas, top);
            }
            
        } catch (SQLException eS) {
            throw new DataBaseDAOException(DataBaseDAOException.CAN_NOT_EXECUTEQUERY
                    + Constantes.SL + eS.getMessage());
        }

        return ranking;        
        
    }

    private Float obtenerDiasPeriodo(Date fechaInicio, Date fechaFin) {
        
                Float dias;
                Calendar cal1 = Calendar.getInstance();
                cal1.setTime(fechaInicio);
                cal1.set(Calendar.HOUR_OF_DAY, 0);
                cal1.set(Calendar.MINUTE, 0);
                cal1.set(Calendar.SECOND, 0);
                long comienzo = cal1.getTimeInMillis();


                Calendar cal2 = Calendar.getInstance();
                cal1.setTime(fechaFin);
                cal1.set(Calendar.HOUR_OF_DAY, 0);
                cal1.set(Calendar.MINUTE, 0);
                cal1.set(Calendar.SECOND, 0);
                long fin = cal2.getTimeInMillis();

                long diasPeriodo = (fin - comienzo) / MILLISECONDS_IN_DAY;
                dias = new Float(diasPeriodo);  
                
                return dias;
    }

    private List<RankingAulaDTO> obtenerRankingAulas(FiltroLocalizacion filtroLoc, FiltroFechas filtroFechas, int top) throws DataBaseDAOException, SQLException {

                List<RankingAulaDTO> ranking = new ArrayList<RankingAulaDTO> ();
        
                //Siempre tienen que llegar fechas, si el usuario no indica ninguna, presentación
                //deberá añadir unas por defecto, ejemplo inicio de la aplicación hasta el día
                //actual
                SimpleDateFormat formato = new SimpleDateFormat("yyyy-MM-dd");
                String fechaDesde = formato.format(filtroFechas.getFechaInicio());
                String fechaHasta = formato.format(filtroFechas.getFechaFin());
                
                //Calculamos el número de días que contiene el período seleccionado
                Float totalDiasPeriodo = obtenerDiasPeriodo(filtroFechas.getFechaInicio(),
                        filtroFechas.getFechaFin());

                // Las ciudades son las que vienen rellenas
                // Si se selecciona solo un país, presentación se encarga de obtener todas
                // las ciudades del mismo
                List<CiudadDTO> listaCiudades = filtroLoc.getCiudades();

                // Construimos la lista de idciudad para obtener solo esas aulas
                String ciudades = "";
                CiudadDTO ciudad = null;
                for(int i=0;i<listaCiudades.size();i++) {
                    ciudad = listaCiudades.get(i);
                    if (i==0) {
                        ciudades = ciudad.getIdCiudad().toString();
                    }else {
                        ciudades += ",'"+ciudad.getIdCiudad().toString()+"'"; 
                    }
                }


                // Obtenemos los datos del Ranking por días
                String sSQL = "SELECT r.idaula as idAula, count(idreserva) as totalReservas,"
                        + "sum(asistentes) as totalAsistentes,sum(importe) as totalImporte,"
                        + "SUM(fechafin-fechaini) as totalDias from reserva r,solicitud s,aula a "
                        + "where s.idsolicitud=r.idreserva and r.estado="+Constantes.RESERVA_CONSUMADA+" and "
                        + "(s.fechaini>='"+fechaDesde+"' and s.fechafin<='"+fechaHasta+"') and r.idaula=a.idaula "
                        + "and a.idciudad in (" + ciudades + ") group by r.idaula";

                ResultSet objRS = super.obtenerConsulta(sSQL);
                Integer dias, reservas, asistentes;
                Float gradoReserva, mediaAsistentes, mediaDiasReserva;
                boolean continuar = true; //variable que controla el número de filas a obtener según el valor de Top
                int numFilas = 0;                
                while (objRS.next()&&continuar) { //por aula

                    RankingAulaDTO rankingAula = new RankingAulaDTO();
                    rankingAula.setAula(objRS.getString("idAula"));
                    
                    dias = objRS.getInt("totalDias");
                    gradoReserva = (dias / totalDiasPeriodo)*100;
                    rankingAula.setGradoReserva(gradoReserva);
                    
                    reservas = objRS.getInt("totalReservas");
                    asistentes = objRS.getInt("totalAsistentes");
                    mediaAsistentes = new Float((asistentes / reservas));
                    rankingAula.setAsistentes(asistentes);
                    rankingAula.setMediaAsistentes(mediaAsistentes);
                    
                    rankingAula.setReservas(reservas);
                    mediaDiasReserva = new Float ((dias / reservas));
                    rankingAula.setMediaDiasReserva(mediaDiasReserva);
                    
                    rankingAula.setFacturacion(objRS.getFloat("totalImporte"));
                    ranking.add(rankingAula);
                    //comprobamos si seguimos obteniendo filas
                    if(top==Constantes.TOP_TODOS) {
                        continuar = true;
                    } else if ((top==Constantes.TOP_10)||(top==Constantes.TOP_20)) {               
                        numFilas++;
                        continuar = numFilas < top;
                    }                     
                }
                
                // Liberamos recursos
                objRS.close();
                objRS = null;
                return ranking;

    }
    
    private List<RankingLocalizacionDTO> obtenerRankingLocalizacion(FiltroLocalizacion filtroLoc, FiltroFechas filtroFechas, int top) throws DataBaseDAOException, SQLException {

                List<RankingLocalizacionDTO> ranking = new ArrayList<RankingLocalizacionDTO> ();
        
                //Siempre tienen que llegar fechas, si el usuario no indica ninguna, presentación
                //deberá añadir unas por defecto, ejemplo inicio de la aplicación hasta el día
                //actual
                SimpleDateFormat formato = new SimpleDateFormat("yyyy-MM-dd");
                String fechaDesde = formato.format(filtroFechas.getFechaInicio());
                String fechaHasta = formato.format(filtroFechas.getFechaFin());
                        //Calculamos el número de días que contiene el período seleccionado
                        Float totalDiasPeriodo = obtenerDiasPeriodo(filtroFechas.getFechaInicio(),
                                filtroFechas.getFechaFin());

                // Las ciudades son las que vienen rellenas
                // Si se selecciona solo un país, presentación se encarga de obtener todas
                // las ciudades del mismo
                List<CiudadDTO> listaCiudades = filtroLoc.getCiudades();

                // Construimos la lista de idciudad para obtener solo esas aulas
                String ciudades = "";
                CiudadDTO ciudad = null;
                for(int i=0;i<listaCiudades.size();i++) {
                    ciudad = listaCiudades.get(i);
                    if (i==0) {
                        ciudades = ciudad.getIdCiudad().toString();
                    }else {
                        ciudades += ",'"+ciudad.getIdCiudad().toString()+"'"; 
                    }
                }


                // Obtenemos los datos del Ranking por días
                String sSQL = "SELECT c.nombre as idCiudad, count(idreserva) as totalReservas,"
                        + "sum(asistentes) as totalAsistentes,sum(importe) as totalImporte,"
                        + "SUM(fechafin-fechaini) as totalDias from reserva r,solicitud s,aula a,ciudad c "
                        + "where s.idsolicitud=r.idreserva and a.idciudad=c.idciudad and "
                        + "(s.fechaini>='"+fechaDesde+"' and s.fechafin<='"+fechaHasta+"') "
                        + "and r.idaula=a.idaula and r.estado="+Constantes.RESERVA_CONSUMADA + " "
                        + "and a.idciudad in ("+ciudades+") group by c.nombre";

                ResultSet objRS = super.obtenerConsulta(sSQL);
                Integer dias, reservas, asistentes;
                Float gradoReserva, mediaAsistentes, mediaDiasReserva;
                boolean continuar = true; //variable que controla el número de filas a obtener según el valor de Top
                int numFilas = 0;                
                while (objRS.next()&&continuar) {

                    RankingLocalizacionDTO rankingLoc = new RankingLocalizacionDTO();
                    rankingLoc.setCiudad(objRS.getString("idCiudad"));
                    
                    dias = objRS.getInt("totalDias");
                    gradoReserva = (dias / totalDiasPeriodo)*100;
                    rankingLoc.setGradoReserva(gradoReserva);
                    
                    reservas = objRS.getInt("totalReservas");
                    asistentes = objRS.getInt("totalAsistentes");
                    mediaAsistentes = new Float((asistentes / reservas));
                    rankingLoc.setAsistentes(asistentes);
                    rankingLoc.setMediaAsistentes(mediaAsistentes);
                    
                    rankingLoc.setReservas(reservas);
                    mediaDiasReserva = new Float ((dias / reservas));
                    rankingLoc.setMediaDiasReserva(mediaDiasReserva);
                    
                    rankingLoc.setFacturacion(objRS.getFloat("totalImporte"));
                    ranking.add(rankingLoc);
                    //comprobamos si seguimos obteniendo filas
                    if(top==Constantes.TOP_TODOS) {
                        continuar = true;
                    } else if ((top==Constantes.TOP_10)||(top==Constantes.TOP_20)) {               
                        numFilas++;
                        continuar = numFilas < top;
                    }                     
                }
                
                // Liberamos recursos
                objRS.close();
                objRS = null;                
                return ranking;
    }
    
    private List<RankingClienteDTO> obtenerRankingCliente(FiltroLocalizacion filtroLoc, FiltroFechas filtroFechas, int top) throws DataBaseDAOException, SQLException {

        List<RankingClienteDTO> ranking = new ArrayList<RankingClienteDTO> ();
        
        //Siempre tienen que llegar fechas, si el usuario no indica ninguna, presentación
        //deberá añadir unas por defecto, ejemplo inicio de la aplicación hasta el día
        //actual
        SimpleDateFormat formato = new SimpleDateFormat("yyyy-MM-dd");
        String fechaDesde = formato.format(filtroFechas.getFechaInicio());
        String fechaHasta = formato.format(filtroFechas.getFechaFin());
        
              //Calculamos el número de días que contiene el período seleccionado
                Float totalDiasPeriodo = obtenerDiasPeriodo(filtroFechas.getFechaInicio(),
                        filtroFechas.getFechaFin());

                // Las ciudades son las que vienen rellenas
                // Si se selecciona solo un país, presentación se encarga de obtener todas
                // las ciudades del mismo
                List<CiudadDTO> listaCiudades = filtroLoc.getCiudades();

                // Construimos la lista de idciudad para obtener solo esas aulas
                String ciudades = "";
                CiudadDTO ciudad = null;
                for(int i=0;i<listaCiudades.size();i++) {
                    ciudad = listaCiudades.get(i);
                    if (i==0) {
                        ciudades = ciudad.getIdCiudad().toString();
                    }else {
                        ciudades += ",'"+ciudad.getIdCiudad().toString()+"'"; 
                    }
                }
                
                // Obtenemos los datos del Ranking por días
                String sSQL = "SELECT u.nombre as idCliente, count(idreserva) as totalReservas,"
                        + "sum(asistentes) as totalAsistentes,sum(importe) as totalImporte,"
                        + "SUM(fechafin-fechaini) as totalDias from reserva r,solicitud s,aula a,usuario u "
                        + "where s.idsolicitud=r.idreserva and s.idcliente=u.idusuario and "
                        + "(s.fechaini>='"+fechaDesde+"' and s.fechafin<='"+fechaHasta+"') "
                        + "and r.idaula=a.idaula and r.estado="+Constantes.RESERVA_CONSUMADA+" "
                        + "and a.idciudad in ("+ciudades+") group by u.nombre";

                ResultSet objRS = super.obtenerConsulta(sSQL);
                Integer dias, reservas, asistentes;
                Float gradoReserva, mediaAsistentes, mediaDiasReserva;
                boolean continuar = true; //variable que controla el número de filas a obtener según el valor de Top
                int numFilas = 0;                
                while (objRS.next()&&continuar) {

                    RankingClienteDTO rankingCliente = new RankingClienteDTO();
                    rankingCliente.setCliente(objRS.getString("idCliente"));
                    
                    dias = objRS.getInt("totalDias");
                    gradoReserva = (dias / totalDiasPeriodo)*100;
                    rankingCliente.setGradoReserva(gradoReserva);
                    
                    reservas = objRS.getInt("totalReservas");
                    asistentes = objRS.getInt("totalAsistentes");
                    mediaAsistentes = new Float((asistentes / reservas));
                    rankingCliente.setAsistentes(asistentes);
                    rankingCliente.setMediaAsistentes(mediaAsistentes);
                    
                    rankingCliente.setReservas(reservas);
                    mediaDiasReserva = new Float ((dias / reservas));
                    rankingCliente.setMediaDiasReserva(mediaDiasReserva);
                    
                    rankingCliente.setFacturacion(objRS.getFloat("totalImporte"));
                    ranking.add(rankingCliente);
                    //comprobamos si seguimos obteniendo filas
                    if(top==Constantes.TOP_TODOS) {
                        continuar = true;
                    } else if ((top==Constantes.TOP_10)||(top==Constantes.TOP_20)) {               
                        numFilas++;
                        continuar = numFilas < top;
                    }                     
                }
                
           // Liberamos recursos
           objRS.close();
           objRS = null;                
           return ranking;
    }

    private List<RankingAulaDTO> obtenerRankingAulaMeses(FiltroLocalizacion filtroLoc, FiltroFechas filtroFechas, int top) throws DataBaseDAOException, SQLException {

                List<RankingAulaDTO> ranking = new ArrayList<RankingAulaDTO> ();
        
                //Siempre tienen que llegar fechas, si el usuario no indica ninguna, presentación
                //deberá añadir unas por defecto, ejemplo inicio de la aplicación hasta el día
                //actual
                SimpleDateFormat formato = new SimpleDateFormat("yyyy-MM-dd");
                Date desde = filtroFechas.getFechaInicio();
                Date hasta = filtroFechas.getFechaFin();
                
                // Las ciudades son las que vienen rellenas
                // Si se selecciona solo un país, presentación se encarga de obtener todas
                // las ciudades del mismo
                List<CiudadDTO> listaCiudades = filtroLoc.getCiudades();                
                // Construimos la lista de idciudad para obtener solo esas aulas
                String ciudades = "";
                CiudadDTO ciudad = null;
                for(int i=0;i<listaCiudades.size();i++) {
                        ciudad = listaCiudades.get(i);
                        if (i==0) {
                            ciudades = ciudad.getIdCiudad().toString();
                        }else {
                            ciudades += ",'"+ciudad.getIdCiudad().toString()+"'"; 
                    }
                }                
                //Como debe ser agrupado por meses (pero dentro del mismo año)
                //obtenemos el mesInicio y el mesFin; posteriormente se buscará
                //las reservas obtenidas desde el día 1 del mes hasta el último
                //dis del mes -28,29,30,31- según corresponda.
                SimpleDateFormat formatoMes = new SimpleDateFormat("MM");
                SimpleDateFormat formatoAnnio = new SimpleDateFormat("yyyy");
                int mesInicio = Integer.parseInt(formatoMes.format(desde));
                int mesFin = Integer.parseInt(formatoMes.format(hasta));
                int annio = Integer.parseInt(formatoAnnio.format(desde));
                int date = 1;
                
                //Calcular los Rankings correspondientes a cada uno de los meses,
                //utilizando para ello el día 1 como fecha de Inicio y el último
                //dia del mes en curo para la fecha de Fin               
                for(int mes=mesInicio; mes<=mesFin; mes++) {            
                    
                    // Obtenermos el último día del mes en curso 
                    Calendar calendario = Calendar.getInstance();
                    calendario.set(annio, mes-1, date);
                    int maxDia = calendario.getActualMaximum(Calendar.DAY_OF_MONTH);
                    //Obtenemos el número de días que contiene el mes seleccionado
                    Float totalDiasPeriodo = new Float(maxDia);
                    
                    String fechaDesde = annio + "-" + mes + "-" + date;
                    String fechaHasta = annio + "-" + mes + "-" + maxDia;
                    
                    // Obtenemos los datos del Ranking por días
                    String sSQL = "SELECT r.idaula as idAula, count(idreserva) as totalReservas,"
                            + "sum(asistentes) as totalAsistentes,sum(importe) as totalImporte,"
                            + "SUM(fechafin-fechaini) as totalDias from reserva r,solicitud s,aula a "
                            + "where s.idsolicitud=r.idreserva and r.estado="+Constantes.RESERVA_CONSUMADA+" and "
                            + "(s.fechaini>='"+fechaDesde+"' and s.fechafin<='"+fechaHasta+"') and r.idaula=a.idaula "
                            + "and a.idciudad in (" + ciudades + ") group by r.idaula";                   
                    
                    ResultSet objRS = super.obtenerConsulta(sSQL);
                    Integer dias, reservas, asistentes;
                    Float gradoReserva, mediaAsistentes, mediaDiasReserva;
                    boolean continuar = true; //variable que controla el número de filas a obtener según el valor de Top
                    int numFilas = 0;                    
                    while (objRS.next()&&continuar) {                                 
                        
                        RankingAulaDTO rankingAula = new RankingAulaDTO();
                        
                        rankingAula.setMes(obtenerLiteralMes(mes));
                        rankingAula.setAula(objRS.getString("idAula"));

                        dias = objRS.getInt("totalDias");
                        gradoReserva = (dias / totalDiasPeriodo)*100;
                        rankingAula.setGradoReserva(gradoReserva);

                        reservas = objRS.getInt("totalReservas");
                        asistentes = objRS.getInt("totalAsistentes");
                        mediaAsistentes = new Float((asistentes / reservas));
                        rankingAula.setAsistentes(asistentes);
                        rankingAula.setMediaAsistentes(mediaAsistentes);

                        rankingAula.setReservas(reservas);
                        mediaDiasReserva = new Float ((dias / reservas));
                        rankingAula.setMediaDiasReserva(mediaDiasReserva);

                        rankingAula.setFacturacion(objRS.getFloat("totalImporte"));
                        ranking.add(rankingAula);
                        //comprobamos si seguimos obteniendo filas
                        if(top==Constantes.TOP_TODOS) {
                            continuar = true;
                        } else if ((top==Constantes.TOP_10)||(top==Constantes.TOP_20)) {               
                            numFilas++;
                            continuar = numFilas < top;
                        }                         
                    }
                   // Liberamos recursos
                   objRS.close();
                   objRS = null;                      
                    
                }// final bucle por meses

                return ranking;
    }

    private List<RankingLocalizacionDTO> obtenerRankingLocalizacionMeses(FiltroLocalizacion filtroLoc, FiltroFechas filtroFechas, int top) throws DataBaseDAOException, SQLException {

                List<RankingLocalizacionDTO> ranking = new ArrayList<RankingLocalizacionDTO> ();
        
                //Siempre tienen que llegar fechas, si el usuario no indica ninguna, presentación
                //deberá añadir unas por defecto, ejemplo inicio de la aplicación hasta el día
                //actual
                SimpleDateFormat formato = new SimpleDateFormat("yyyy-MM-dd");
                Date desde = filtroFechas.getFechaInicio();
                Date hasta = filtroFechas.getFechaFin();
                
                // Las ciudades son las que vienen rellenas
                // Si se selecciona solo un país, presentación se encarga de obtener todas
                // las ciudades del mismo
                List<CiudadDTO> listaCiudades = filtroLoc.getCiudades();                
                // Construimos la lista de idciudad para obtener solo esas aulas
                String ciudades = "";
                CiudadDTO ciudad = null;
                for(int i=0;i<listaCiudades.size();i++) {
                        ciudad = listaCiudades.get(i);
                        if (i==0) {
                            ciudades = ciudad.getIdCiudad().toString();
                        }else {
                            ciudades += ",'"+ciudad.getIdCiudad().toString()+"'"; 
                    }
                }                
                //Como debe ser agrupado por meses (pero dentro del mismo año)
                //obtenemos el mesInicio y el mesFin; posteriormente se buscará
                //las reservas obtenidas desde el día 1 del mes hasta el último
                //dis del mes -28,29,30,31- según corresponda.
                SimpleDateFormat formatoMes = new SimpleDateFormat("MM");
                SimpleDateFormat formatoAnnio = new SimpleDateFormat("yyyy");
                int mesInicio = Integer.parseInt(formatoMes.format(desde));
                int mesFin = Integer.parseInt(formatoMes.format(hasta));
                int annio = Integer.parseInt(formatoAnnio.format(desde));
                int date = 1;
                
                //Calcular los Rankings correspondientes a cada uno de los meses,
                //utilizando para ello el día 1 como fecha de Inicio y el último
                //dia del mes en curo para la fecha de Fin
                for(int mes=mesInicio; mes<=mesFin; mes++) {                 
                
                    // Obtenermos el último día del mes en curso 
                    Calendar calendario = Calendar.getInstance();
                    calendario.set(annio, mes-1, date);
                    int maxDia = calendario.getActualMaximum(Calendar.DAY_OF_MONTH);
                    //Obtenemos el número de días que contiene el mes seleccionado
                    Float totalDiasPeriodo = new Float(maxDia);
                    
                    String fechaDesde = annio + "-" + mes + "-" + date;
                    String fechaHasta = annio + "-" + mes + "-" + maxDia;
                    // Obtenemos los datos del Ranking por días
                    String sSQL = "SELECT c.nombre as idCiudad, count(idreserva) as totalReservas,"
                            + "sum(asistentes) as totalAsistentes,sum(importe) as totalImporte,"
                            + "SUM(fechafin-fechaini) as totalDias from reserva r,solicitud s,aula a,ciudad c "
                            + "where s.idsolicitud=r.idreserva and a.idciudad=c.idciudad and "
                            + "(s.fechaini>='"+fechaDesde+"' and s.fechafin<='"+fechaHasta+"') and "
                            + "r.idaula=a.idaula and r.estado="+Constantes.RESERVA_CONSUMADA+" "
                            + "and a.idciudad in ("+ciudades+") group by c.nombre";

                    ResultSet objRS = super.obtenerConsulta(sSQL);
                    Integer dias, reservas, asistentes;
                    Float gradoReserva, mediaAsistentes, mediaDiasReserva;
                    boolean continuar = true; //variable que controla el número de filas a obtener según el valor de Top
                    int numFilas = 0;                    
                    while (objRS.next()&&continuar) {

                        RankingLocalizacionDTO rankingLoc = new RankingLocalizacionDTO();
                        rankingLoc.setMes(obtenerLiteralMes(mes));
                        rankingLoc.setCiudad(objRS.getString("idCiudad"));

                        dias = objRS.getInt("totalDias");
                        gradoReserva = (dias / totalDiasPeriodo)*100;
                        rankingLoc.setGradoReserva(gradoReserva);

                        reservas = objRS.getInt("totalReservas");
                        asistentes = objRS.getInt("totalAsistentes");
                        mediaAsistentes = new Float((asistentes / reservas));
                        rankingLoc.setAsistentes(asistentes);
                        rankingLoc.setMediaAsistentes(mediaAsistentes);

                        rankingLoc.setReservas(reservas);
                        mediaDiasReserva = new Float ((dias / reservas));
                        rankingLoc.setMediaDiasReserva(mediaDiasReserva);

                        rankingLoc.setFacturacion(objRS.getFloat("totalImporte"));
                        ranking.add(rankingLoc);
                        //comprobamos si seguimos obteniendo filas
                        if(top==Constantes.TOP_TODOS) {
                            continuar = true;
                        } else if ((top==Constantes.TOP_10)||(top==Constantes.TOP_20)) {               
                            numFilas++;
                            continuar = numFilas < top;
                        }                         
                    }
                   // Liberamos recursos
                   objRS.close();
                   objRS = null;                      
                }// final bucle por meses
                
           return ranking;
    }

    private List<RankingClienteDTO> obtenerRankingClienteMeses(FiltroLocalizacion filtroLoc, FiltroFechas filtroFechas, int top) throws DataBaseDAOException, SQLException {

        List<RankingClienteDTO> ranking = new ArrayList<RankingClienteDTO> ();
        
                //Siempre tienen que llegar fechas, si el usuario no indica ninguna, presentación
                //deberá añadir unas por defecto, ejemplo inicio de la aplicación hasta el día
                //actual
                SimpleDateFormat formato = new SimpleDateFormat("yyyy-MM-dd");
                Date desde = filtroFechas.getFechaInicio();
                Date hasta = filtroFechas.getFechaFin();
                
                // Las ciudades son las que vienen rellenas
                // Si se selecciona solo un país, presentación se encarga de obtener todas
                // las ciudades del mismo
                List<CiudadDTO> listaCiudades = filtroLoc.getCiudades();                
                // Construimos la lista de idciudad para obtener solo esas aulas
                String ciudades = "";
                CiudadDTO ciudad = null;
                for(int i=0;i<listaCiudades.size();i++) {
                        ciudad = listaCiudades.get(i);
                        if (i==0) {
                            ciudades = ciudad.getIdCiudad().toString();
                        }else {
                            ciudades += ",'"+ciudad.getIdCiudad().toString()+"'"; 
                    }
                }                
                //Como debe ser agrupado por meses (pero dentro del mismo año)
                //obtenemos el mesInicio y el mesFin; posteriormente se buscará
                //las reservas obtenidas desde el día 1 del mes hasta el último
                //dis del mes -28,29,30,31- según corresponda.
                SimpleDateFormat formatoMes = new SimpleDateFormat("MM");
                SimpleDateFormat formatoAnnio = new SimpleDateFormat("yyyy");
                int mesInicio = Integer.parseInt(formatoMes.format(desde));
                int mesFin = Integer.parseInt(formatoMes.format(hasta));
                int annio = Integer.parseInt(formatoAnnio.format(desde));
                int date = 1;
 
        
                //Calcular los Rankings correspondientes a cada uno de los meses,
                //utilizando para ello el día 1 como fecha de Inicio y el último
                //dia del mes en curo para la fecha de Fin
                for(int mes=mesInicio; mes<=mesFin; mes++) {
                    
                    // Obtenermos el último día del mes en curso 
                    Calendar calendario = Calendar.getInstance();
                    calendario.set(annio, mes-1, date);
                    int maxDia = calendario.getActualMaximum(Calendar.DAY_OF_MONTH);
                    //Obtenemos el número de días que contiene el mes seleccionado
                    Float totalDiasPeriodo = new Float(maxDia);
                    
                    String fechaDesde = annio + "-" + mes + "-" + date;
                    String fechaHasta = annio + "-" + mes + "-" + maxDia;

                    // Obtenemos los datos del Ranking por días
                    String sSQL = "SELECT u.nombre as idCliente, count(idreserva) as totalReservas,"
                            + "sum(asistentes) as totalAsistentes,sum(importe) as totalImporte,"
                            + "SUM(fechafin-fechaini) as totalDias from reserva r,solicitud s,aula a,usuario u "
                            + "where s.idsolicitud=r.idreserva and s.idcliente=u.idusuario and "
                            + "(s.fechaini>='"+fechaDesde+"' and s.fechafin<='"+fechaHasta+"') and "
                            + "r.idaula=a.idaula and r.estado="+Constantes.RESERVA_CONSUMADA +" "
                            + "and a.idciudad in ("+ciudades+") group by u.nombre";

                    ResultSet objRS = super.obtenerConsulta(sSQL);
                    Integer dias, reservas, asistentes;
                    Float gradoReserva, mediaAsistentes, mediaDiasReserva;
                    boolean continuar = true; //variable que controla el número de filas a obtener según el valor de Top
                    int numFilas = 0;                    
                    while (objRS.next()&&continuar) {

                        RankingClienteDTO rankingCliente = new RankingClienteDTO();
                        rankingCliente.setMes(obtenerLiteralMes(mes));
                        rankingCliente.setCliente(objRS.getString("idCliente"));

                        dias = objRS.getInt("totalDias");
                        gradoReserva = (dias / totalDiasPeriodo)*100;
                        rankingCliente.setGradoReserva(gradoReserva);

                        reservas = objRS.getInt("totalReservas");
                        asistentes = objRS.getInt("totalAsistentes");
                        mediaAsistentes = new Float((asistentes / reservas));
                        rankingCliente.setAsistentes(asistentes);
                        rankingCliente.setMediaAsistentes(mediaAsistentes);

                        rankingCliente.setReservas(reservas);
                        mediaDiasReserva = new Float ((dias / reservas));
                        rankingCliente.setMediaDiasReserva(mediaDiasReserva);

                        rankingCliente.setFacturacion(objRS.getFloat("totalImporte"));
                        ranking.add(rankingCliente);
                        //comprobamos si seguimos obteniendo filas
                        if(top==Constantes.TOP_TODOS) {
                            continuar = true;
                        } else if ((top==Constantes.TOP_10)||(top==Constantes.TOP_20)) {               
                            numFilas++;
                            continuar = numFilas < top;
                        }                         
                    }
                   // Liberamos recursos
                   objRS.close();
                   objRS = null;                      
                }// final bucle por meses
           return ranking;
    }

    private String obtenerLiteralMes(int mes) {
        String textoMes = "";
        switch (mes) {
            case 1:  textoMes="Enero"; break;
            case 2:  textoMes="Febrero"; break;
            case 3:  textoMes="Marzo"; break;
            case 4:  textoMes="Abril"; break;
            case 5:  textoMes="Mayo"; break;
            case 6:  textoMes="Junio"; break;
            case 7:  textoMes="Julio"; break;
            case 8:  textoMes="Agosto"; break;
            case 9:  textoMes="Septiembre"; break;
            case 10: textoMes="Octubre"; break;
            case 11: textoMes="Noviembre"; break;
            case 12: textoMes="Diciembre"; break;            
        }
        return textoMes;
    }
    
    
}
